home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / datatypes / font_dt / src / dispatch.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  14KB  |  463 lines

  1. /*
  2. **    dispatch.c - dispatcher for Font DataType class
  3. **    Copyright © 1995 Michael Letowski
  4. */
  5.  
  6. #include <exec/types.h>
  7. #include <exec/memory.h>
  8. #include <dos/dos.h>
  9. #include <dos/rdargs.h>
  10. #include <graphics/displayinfo.h>
  11. #include <graphics/gfx.h>
  12. #include <graphics/modeid.h>
  13. #include <graphics/rastport.h>
  14. #include <graphics/text.h>
  15. #include <intuition/classes.h>
  16. #include <datatypes/datatypesclass.h>
  17. #include <datatypes/pictureclass.h>
  18. #include <diskfont/diskfont.h>
  19. #include <datatypes/datatypes.h>
  20. #include <diskfont/diskfonttag.h>
  21. #include <utility/hooks.h>
  22. #include <utility/tagitem.h>
  23. #include <support/types.h>
  24. #include <support/graphics.h>
  25.  
  26. #include <stdlib.h>
  27.  
  28. #include <proto/dos.h>
  29. #include <proto/exec.h>
  30. #include <proto/diskfont.h>
  31. #include <proto/datatypes.h>
  32. #include <proto/graphics.h>
  33. #include <proto/intuition.h>
  34. #include <proto/utility.h>
  35. #include <clib/support_protos.h>
  36.  
  37. #include "classbase.h"
  38. #include "dispatch.h"
  39. #include "prefs.h"
  40. #include "otag.h"
  41.  
  42. #define IDS_CNT                4
  43.  
  44. #define COL_WHITE            0xFF
  45. #define COL_BLACK            0x00
  46.  
  47. #define DEF_XDPI            72
  48. #define DEF_YDPI            80
  49.  
  50. /* 256 for ASCII set, 2 for terminator */
  51. #define MAX_CHAR            (256+2)
  52. /* 32 chars for font name, 6 for size, 2 for terminator */
  53. #define MAX_CHAR2            (32+6+2)
  54. /* Total number of strings */
  55. #define MAX_STRING        32
  56.  
  57. /* Get font's name */
  58. #define FontName(f)        ((f)->tf_Message.mn_Node.ln_Name)
  59.  
  60. typedef int (SFUNC)(void const*, void const *);
  61.  
  62. STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
  63. STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs);
  64.  
  65. /* Font management */
  66. STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
  67.                                                                         struct FontContentsHeader *fch, STRPTR name);
  68. STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt);
  69. /* Rendering */
  70. STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  71.                                         struct TextFont *f, ULONG *w, ULONG *h);
  72. STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  73.                                         struct TextFont **f, ULONG cnt, ULONG w);
  74. STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt, 
  75.                                                         struct TextFont *f, ULONG *cnt);
  76. STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2);
  77.  
  78. /* DataTypes stubs */
  79. STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
  80. STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
  81.  
  82. Class *InitClass(struct ClassBase *cb)
  83. {
  84.     Class *CL;
  85.  
  86.     /* Create our class (no instance) */
  87.     if(CL=MakeClass(FONTDTCLASS,PICTUREDTCLASS,NULL,NULL,0))
  88.     {
  89.         CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
  90.         CL->cl_UserData=(ULONG)cb;
  91.         AddClass(CL);
  92.     }
  93.     return(CL);
  94. }    /* InitClass */
  95.  
  96. STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
  97. {
  98.     struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
  99.     Object *Obj;
  100.  
  101.     switch(msg->MethodID)
  102.     {
  103.         case OM_NEW:                                                                /* We know this method */
  104.             if(Obj=(Object *)DoSuperMethodA(cl,o,msg))
  105.                 unless(GetFont(cb,Obj,((struct opSet *)msg)->ops_AttrList))
  106.                 {
  107.                     CoerceMethod(cl,Obj,OM_DISPOSE);
  108.                     return(NULL);
  109.                 }
  110.             break;
  111.         default:                                                                        /* Let the superclass handle it */
  112.             Obj=(Object *)DoSuperMethodA(cl,o,msg);
  113.             break;
  114.     }
  115.     return(Obj);
  116. }
  117.  
  118. STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs)
  119. {
  120.     STATIC CONST ULONG SourceIDs[IDS_CNT]=                    /* Font flag->mode selector */
  121.     {
  122.         LORES_KEY,HIRES_KEY,LORESLACE_KEY,HIRESLACE_KEY
  123.     };    /* ModeIDs */
  124.  
  125.     struct RastPort RP;
  126.     struct Opts Opts;
  127.     struct BitMapHeader *BMHD=NULL;
  128.     struct ColorRegister *CMap=NULL;
  129.     LONG *CRegs=NULL;
  130.     struct FileInfoBlock *FIB;
  131.     struct FontContentsHeader *FCH;
  132.     struct TextFont **Fonts,*F;
  133.     struct ColorTextFont *CF;
  134.     struct ColorFontColors *CFC;
  135.     struct PrefsHandle *PH;
  136.  
  137.     STRPTR Name=NULL,Title;                                                /* Font file name & picture title */
  138.     BPTR DirLock,FH=0;
  139.     ULONG TallWide,ModeID;
  140.     ULONG Width,Height,Depth,NumColors;
  141.     ULONG I,J,NumFonts;
  142.     UBYTE ForeRed,ForeGrn,ForeBlu,BackRed,BackGrn,BackBlu;
  143.     LBOOL Result=FALSE;
  144.  
  145.     /* Read preferences */
  146.     PH=GetFontPrefs(cb,&Opts);
  147.  
  148.     /* Get default title */
  149.     Title=(STRPTR)GetTagData(DTA_Name,NULL,attrs);
  150.  
  151.     /* Get file handle and BitMapHeader */
  152.     LocGetDTAttrs(cb,o,DTA_Handle,&FH,PDTA_BitMapHeader,&BMHD,TAG_DONE);
  153.     try(FH && BMHD,    EXIT);
  154.  
  155.     /* Get font file name */
  156.     try(FIB=AllocDosObject(DOS_FIB,NULL),    NO_FIB);/* Create FileInfoBlock */
  157.     if(ExamineFH(FH,FIB))                                                    /* Examine it */
  158.         Name=FIB->fib_FileName;                                            /* Get name pointer */
  159.     unless(Name)                                                                    /* Still no name */
  160.         if(Title)                                                                        /* Use title to get name */
  161.             Name=FilePart(Title);                                            /* Get file part of title */
  162.     try(Name,    NO_NAME);
  163.  
  164.     /* Get font */
  165.     try(DirLock=ParentOfFH(FH),                            NO_LOCK);
  166.     try(FCH=NewFC(cb,DirLock,Name),                    NO_FCH);
  167.     try(Fonts=OpenFonts(cb,&Opts,FCH,Name),    NO_FONTS);
  168.     NumFonts=FCH->fch_NumEntries;
  169.  
  170.     /* Set colours */
  171.     ForeRed=ForeGrn=ForeBlu=COL_BLACK;
  172.     if(Opts.opt_ForeRed)    ForeRed=clamp(*Opts.opt_ForeRed,0,255);
  173.     if(Opts.opt_ForeGrn)    ForeGrn=clamp(*Opts.opt_ForeGrn,0,255);
  174.     if(Opts.opt_ForeBlu)    ForeBlu=clamp(*Opts.opt_ForeBlu,0,255);
  175.     BackRed=BackGrn=BackBlu=COL_WHITE;
  176.     if(Opts.opt_BackRed)    BackRed=clamp(*Opts.opt_BackRed,0,255);
  177.     if(Opts.opt_BackGrn)    BackGrn=clamp(*Opts.opt_BackGrn,0,255);
  178.     if(Opts.opt_BackBlu)    BackBlu=clamp(*Opts.opt_BackBlu,0,255);
  179.  
  180.     /* Calculate sizes */
  181.     TallWide=0;
  182.     Width=Height=0;
  183.     Depth=1;
  184.     InitRastPort(&RP);                                                        /* Set up RastPort - here! */
  185.     for(I=0; I<NumFonts; I++)
  186.         if(F=Fonts[I])                                                            /* Opened successfully */
  187.         {
  188.             try(GetWH(cb,&RP,&Opts,F,&Width,&Height),    ERROR);
  189.             if(ftst(F->tf_Style,FSF_COLORFONT))                /* This is ColorFont */
  190.             {
  191.                 CF=(struct ColorTextFont *)F;
  192.                 if(CF->ctf_Depth>Depth)                                    /* Deeper? */
  193.                     Depth=CF->ctf_Depth;                                    /* Set new depth */
  194.             }
  195.             TallWide=(F->tf_Flags & (FPF_TALLDOT | FPF_WIDEDOT))>>FPB_TALLDOT;
  196.         }
  197.  
  198.     /* Set up BitMap header */
  199.     BMHD->bmh_Width=Width;                                                /* Fill in informations */
  200.     BMHD->bmh_Height=Height;
  201.     BMHD->bmh_Depth=Depth;
  202.     NumColors=1<<Depth;
  203.  
  204.     /* Get display mode id */
  205.     ModeID=BestModeID(BIDTAG_DesiredWidth,    Width,
  206.                                         BIDTAG_DesiredHeight,    Height,
  207.                                         BIDTAG_Depth,                    Depth,
  208.                                         BIDTAG_SourceID,            SourceIDs[TallWide & (IDS_CNT-1)],
  209.                                         TAG_DONE);
  210.  
  211.     /* Set colors */
  212.     LocSetDTAttrs(cb,o,PDTA_NumColors,NumColors,TAG_DONE);
  213.     LocGetDTAttrs(cb,o,PDTA_ColorRegisters,&CMap,PDTA_CRegs,&CRegs,TAG_DONE);
  214.     try(CMap && CRegs,    ERROR);
  215.     if(Depth==1)                                                                    /* B&W font */
  216.     {
  217.         if(Opts.opt_Inverse)
  218.         {
  219.             swap(ForeRed,BackRed);
  220.             swap(ForeGrn,BackGrn);
  221.             swap(ForeBlu,BackBlu);
  222.         }
  223.         CMap[0].red=BackRed;    CMap[0].green=BackGrn;    CMap[0].blue=BackBlu;
  224.         CMap[1].red=ForeRed;    CMap[1].green=ForeGrn;    CMap[1].blue=ForeBlu;
  225.         CRegs[0]=Color32(BackRed);        CRegs[3]=Color32(ForeRed);
  226.         CRegs[1]=Color32(BackGrn);        CRegs[4]=Color32(ForeGrn);
  227.         CRegs[2]=Color32(BackBlu);        CRegs[5]=Color32(ForeBlu);
  228.     }
  229.     else                                                                                    /* Some color fonts */
  230.         for(I=0; I<NumFonts; I++)
  231.             if(F=Fonts[I])
  232.                 if(ftst(F->tf_Style,FSF_COLORFONT))
  233.                 {
  234.                     CF=(struct ColorTextFont *)F;
  235.                     if(CFC=CF->ctf_ColorFontColors)                /* Color map exists */
  236.                         for(J=0; J<CFC->cfc_Count; J++)            /* Fore each color in table */
  237.                         {
  238.                             CMap[J].red=        (CFC->cfc_ColorTable[J] & 0x0F00)>>4;
  239.                             CRegs[J*3+0]=        Color32(CMap[J].red);
  240.                             CMap[J].green=    (CFC->cfc_ColorTable[J] & 0x00F0);
  241.                             CRegs[J*3+1]=        Color32(CMap[J].green);
  242.                             CMap[J].blue=        (CFC->cfc_ColorTable[J] & 0x000F)<<4;
  243.                             CRegs[J*3+2]=        Color32(CMap[J].blue);
  244.                         }
  245.                 }
  246.  
  247.     /* Prepare bitmap */
  248.     try(RP.BitMap=AllocBitMap(BMHD->bmh_Width,BMHD->bmh_Height,BMHD->bmh_Depth,
  249.                                                         BMF_CLEAR | BMF_INTERLEAVED,NULL),
  250.             ERROR);
  251.  
  252.     /* Do rendering */
  253.     if(Render(cb,&RP,&Opts,Fonts,NumFonts,Width))
  254.     {
  255.         /* Set attributes of destination picture */
  256.         LocSetDTAttrs(cb,o,DTA_ObjName,                Title,
  257.                                                 DTA_NominalHoriz,    BMHD->bmh_Width,
  258.                                                 DTA_NominalVert,    BMHD->bmh_Height,
  259.                                                 PDTA_BitMap,            RP.BitMap,
  260.                                                 PDTA_ModeID,            ModeID,
  261.                                                 TAG_DONE);
  262.         Result=TRUE;
  263.     }
  264.     else
  265.         FreeBitMap(RP.BitMap);
  266.  
  267.     /* Cleanup */
  268.     catch(ERROR,        );
  269.     catch(NO_FONTS,    CloseFonts(cb,Fonts,NumFonts));
  270.     catch(NO_FCH,        DisposeFC(cb,FCH));
  271.     catch(NO_LOCK,    UnLock(DirLock));
  272.     catch(NO_NAME,    );
  273.     catch(NO_FIB,        FreeDosObject(DOS_FIB,FIB));    /* MUST be freed here, not before! */
  274.     catch(EXIT,            );
  275.     if(PH)                    FreeFontPrefs(cb,PH);
  276.     return(Result);
  277. }    /* GetFont */
  278.  
  279.  
  280. /****************************************************************************/
  281. /*                             Font management                              */
  282. /****************************************************************************/
  283.  
  284. STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
  285.                                                                         struct FontContentsHeader *fch, STRPTR name)
  286. {
  287.     struct TagItem MyTags[]=
  288.     {
  289.         {TA_DeviceDPI,    0},
  290.         {TAG_DONE,            0}
  291.     };    /* MyTags */
  292.     struct TTextAttr TTA;
  293.     struct TextFont **Fonts;
  294.     struct TFontContents *TFC;
  295.     LONG XDPI,YDPI;
  296.     ULONG I,NumEntries=fch->fch_NumEntries;
  297.     LBOOL One=FALSE;                                                            /* Got at least one size */
  298.  
  299.     try(Fonts=AllocVec(NumEntries*sizeof(APTR),MEMF_CLEAR),    NO_FONTS);
  300.     for(I=0; I<NumEntries; I++)
  301.     {
  302.         TFC=&TFontContents(fch)[I];                                /* Get FontContents */
  303.         TTA.tta_Name=name;                                                /* Copy attrs */
  304.         TTA.tta_YSize=TFC->tfc_YSize;
  305.         TTA.tta_Style=TFC->tfc_Style;
  306.         TTA.tta_Flags=TFC->tfc_Flags | FPF_DISKFONT;
  307.         if(ftst(TFC->tfc_Style,FSF_TAGGED))                /* Tags should be set */
  308.             TTA.tta_Tags=(struct TagItem *)
  309.                                         &TFC->tfc_FileName
  310.                                             [MAXFONTPATH-(TFC->tfc_TagCount*sizeof(struct TagItem))];
  311.         else if(opts->opt_XDPI && opts->opt_YDPI)    /* Set our own DPI tags */
  312.         {
  313.             XDPI=clamp(*opts->opt_XDPI,1,65535);
  314.             YDPI=clamp(*opts->opt_YDPI,1,65535);
  315.             MyTags[0].ti_Data=(XDPI<<16) | YDPI;
  316.             TTA.tta_Tags=MyTags;
  317.             fset(TTA.tta_Style,FSF_TAGGED);
  318.         }
  319.         if(Fonts[I]=OpenDiskFont((struct TextAttr *)&TTA))
  320.             One=TRUE;
  321.     }
  322.     if(One)                                                                                /* Got at least one font */
  323.     {                                                                                            /* Sort by size */
  324.         qsort(Fonts,NumEntries,sizeof(APTR),(SFUNC *)SortFunc);
  325.         return(Fonts);
  326.     }
  327.     else
  328.         SetIoErr(ERROR_OBJECT_NOT_FOUND);                        /* Set error */
  329.  
  330.     catch(NO_FONTS,    FreeVec(Fonts));
  331.     return(NULL);
  332. }    /* OpenFonts */
  333.  
  334. STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt)
  335. {
  336.     ULONG I;
  337.  
  338.     for(I=0; I<cnt; I++)
  339.         if(f[I])
  340.             CloseFont(f[I]);
  341.     FreeVec(f);
  342. }    /* CloseFonts */
  343.  
  344.  
  345. /****************************************************************************/
  346. /*                                Rendering                                 */
  347. /****************************************************************************/
  348.  
  349. STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  350.                                         struct TextFont *f, ULONG *w, ULONG *h)
  351. {
  352.     STRPTR CurStr,*Strs;
  353.     ULONG W,J,SCnt;
  354.  
  355.     if(Strs=PrepStrings(cb,opt,f,&SCnt))                    /* Allocate and init strings */
  356.     {
  357.         /* Calculate sizes */
  358.         SetFont(rp,f);
  359.         for(J=0; J<SCnt; J++)
  360.         {
  361.             CurStr=Strs[J];
  362.             W=TextLength(rp,CurStr,strlen(CurStr));        /* Calculate len of this line */
  363.             if(W>*w)                                                                    /* If larger... */
  364.                 *w=W;                                                                        /* Make it new width */
  365.             *h+=f->tf_YSize;                                                    /* Add to height */
  366.         }
  367.         FreeVec(Strs);                                                            /* Free strings */
  368.     }
  369.     return(Strs!=NULL);
  370. }    /* GetWH */
  371.  
  372. STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  373.                                         struct TextFont **f, ULONG cnt, ULONG w)
  374. {
  375.     struct TextFont *F;
  376.     STRPTR CurStr,*Strs;
  377.     ULONG SCnt,I,J,X,Y=0;
  378.     LBOOL Rendered=FALSE;
  379.  
  380.     for(I=0; I<cnt; I++)                                                    /* For each font size */
  381.         if(F=f[I])                                                                    /* Size opened? */
  382.             if(Strs=PrepStrings(cb,opt,F,&SCnt))            /* Allocate and init strings */
  383.             {
  384.                 Rendered=TRUE;
  385.                 /* Do rendering */
  386.                 SetFont(rp,F);                                                    /* Make it current font */
  387.                 for(J=0; J<SCnt; J++)
  388.                 {
  389.                     CurStr=Strs[J];
  390.                     X=opt->opt_Center ? (w-TextLength(rp,CurStr,strlen(CurStr)))/2 : 0;
  391.                     Move(rp,X,Y+F->tf_Baseline);
  392.                     Text(rp,CurStr,strlen(CurStr));
  393.                     Y+=F->tf_YSize;
  394.                 }
  395.                 FreeVec(Strs);                                                    /* Free strings */
  396.             }
  397.     return(Rendered);
  398. }    /* Render */
  399.  
  400. STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt, 
  401.                                                         struct TextFont *f, ULONG *cnt)
  402. {
  403.     STRPTR S1,S2,CurStr;
  404.     STRPTR *Strs,*Ss;
  405.     ULONG I,Cnt,Temp;
  406.  
  407.     /* Calculate number of strings */
  408.     Cnt=2;
  409.     if(Ss=opt->opt_Strings)                                                /* Strings given */
  410.         while(CurStr=*Ss++)                                                    /* For each string */
  411.             if(*CurStr)                                                                /* Non-empty string */
  412.                 Cnt++;                                                                    /* Increase count */
  413.  
  414.     /* Allocate and fill strings array */
  415.     if(Strs=AllocVec(Cnt*sizeof(STRPTR)+MAX_CHAR+MAX_CHAR2,MEMF_CLEAR))
  416.     {
  417.         S1=(STRPTR)Strs+Cnt*sizeof(STRPTR);
  418.         S2=S1+MAX_CHAR;
  419.         Cnt=0;
  420.         if(opt->opt_FontName && FontName(f))                /* FontName - first */
  421.         {
  422.             SNPrintf(S2,MAX_CHAR-1,"%s %ld",FontName(f),f->tf_YSize);
  423.             Strs[Cnt++]=S2;                                                        /* Init strings array */
  424.         }
  425.         Temp=Cnt;
  426.         if(Ss=opt->opt_Strings)                                            /* User's strings given */
  427.             while(CurStr=*Ss++)                                                /* While array not filled */
  428.                 if(*CurStr)                                                            /* Non-empty string */
  429.                     Strs[Cnt++]=CurStr;                                        /* Fill in array */
  430.         if(Cnt==0 || !Ss && Cnt==Temp)                            /* Use charset */
  431.         {
  432.             for(I=f->tf_LoChar; I<=f->tf_HiChar; I++)
  433.                 S1[I - f->tf_LoChar]=I ? (CHAR)I : ' ';    /* Make ASCII array */
  434.             Strs[Cnt++]=S1;
  435.         }
  436.         *cnt=Cnt;
  437.     }
  438.     return(Strs);
  439. }    /* PrepStrings */
  440.  
  441. STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2)
  442. {
  443.     if(*tf1 && *tf2)    return((LONG)(*tf1)->tf_YSize - (*tf2)->tf_YSize);
  444.     else if(*tf1)            return(-1);
  445.     else if(*tf2)            return(1);
  446.     else                            return(0);
  447. }    /* SortFunc */
  448.  
  449.  
  450. /****************************************************************************/
  451. /*                             DataTypes stubs                              */
  452. /****************************************************************************/
  453.  
  454. STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
  455. {
  456.     return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
  457. }    /* LocSetDTAttrs */
  458.  
  459. STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
  460. {
  461.     return(GetDTAttrsA(o,(struct TagItem *)&data));
  462. }    /* LocGetDTAttrs */
  463.